import ctypes
import ctypes.util
import logging
import os
from typing import List, Optional, Dict, Any

logger = logging.getLogger(__name__)

# seccomp常量
SECCOMP_MODE_FILTER = 2
SECCOMP_RET_KILL = 0x00000000
SECCOMP_RET_ALLOW = 0x7fff0000
SECCOMP_RET_ERRNO = 0x00050000

# 系统调用编号（x86_64）
SYSCALLS = {
    'read': 0,
    'write': 1,
    'open': 2,
    'close': 3,
    'stat': 4,
    'fstat': 5,
    'lstat': 6,
    'poll': 7,
    'lseek': 8,
    'mmap': 9,
    'mprotect': 10,
    'munmap': 11,
    'brk': 12,
    'rt_sigaction': 13,
    'rt_sigprocmask': 14,
    'rt_sigreturn': 15,
    'ioctl': 16,
    'pread64': 17,
    'pwrite64': 18,
    'readv': 19,
    'writev': 20,
    'access': 21,
    'pipe': 22,
    'select': 23,
    'sched_yield': 24,
    'mremap': 25,
    'msync': 26,
    'mincore': 27,
    'madvise': 28,
    'shmget': 29,
    'shmat': 30,
    'shmctl': 31,
    'dup': 32,
    'dup2': 33,
    'pause': 34,
    'nanosleep': 35,
    'getitimer': 36,
    'alarm': 37,
    'setitimer': 38,
    'getpid': 39,
    'sendfile': 40,
    'socket': 41,
    'connect': 42,
    'accept': 43,
    'sendto': 44,
    'recvfrom': 45,
    'sendmsg': 46,
    'recvmsg': 47,
    'shutdown': 48,
    'bind': 49,
    'listen': 50,
    'getsockname': 51,
    'getpeername': 52,
    'socketpair': 53,
    'setsockopt': 54,
    'getsockopt': 55,
    'clone': 56,
    'fork': 57,
    'vfork': 58,
    'execve': 59,
    'exit': 60,
    'wait4': 61,
    'kill': 62,
    'uname': 63,
    'semget': 64,
    'semop': 65,
    'semctl': 66,
    'shmdt': 67,
    'msgget': 68,
    'msgsnd': 69,
    'msgrcv': 70,
    'msgctl': 71,
    'fcntl': 72,
    'flock': 73,
    'fsync': 74,
    'fdatasync': 75,
    'truncate': 76,
    'ftruncate': 77,
    'getdents': 78,
    'getcwd': 79,
    'chdir': 80,
    'fchdir': 81,
    'rename': 82,
    'mkdir': 83,
    'rmdir': 84,
    'creat': 85,
    'link': 86,
    'unlink': 87,
    'symlink': 88,
    'readlink': 89,
    'chmod': 90,
    'fchmod': 91,
    'chown': 92,
    'fchown': 93,
    'lchown': 94,
    'umask': 95,
    'gettimeofday': 96,
    'getrlimit': 97,
    'getrusage': 98,
    'sysinfo': 99,
    'times': 100,
    'ptrace': 101,
    'getuid': 102,
    'syslog': 103,
    'getgid': 104,
    'setuid': 105,
    'setgid': 106,
    'geteuid': 107,
    'getegid': 108,
    'setpgid': 109,
    'getppid': 110,
    'getpgrp': 111,
    'setsid': 112,
    'setreuid': 113,
    'setregid': 114,
    'getgroups': 115,
    'setgroups': 116,
    'setresuid': 117,
    'getresuid': 118,
    'setresgid': 119,
    'getresgid': 120,
    'getpgid': 121,
    'setfsuid': 122,
    'setfsgid': 123,
    'getsid': 124,
    'capget': 125,
    'capset': 126,
    'rt_sigpending': 127,
    'rt_sigtimedwait': 128,
    'rt_sigqueueinfo': 129,
    'rt_sigsuspend': 130,
    'sigaltstack': 131,
    'utime': 132,
    'mknod': 133,
    'uselib': 134,
    'personality': 135,
    'ustat': 136,
    'statfs': 137,
    'fstatfs': 138,
    'sysfs': 139,
    'getpriority': 140,
    'setpriority': 141,
    'sched_setparam': 142,
    'sched_getparam': 143,
    'sched_setscheduler': 144,
    'sched_getscheduler': 145,
    'sched_get_priority_max': 146,
    'sched_get_priority_min': 147,
    'sched_rr_get_interval': 148,
    'mlock': 149,
    'munlock': 150,
    'mlockall': 151,
    'munlockall': 152,
    'vhangup': 153,
    'modify_ldt': 154,
    'pivot_root': 155,
    '_sysctl': 156,
    'prctl': 157,
    'arch_prctl': 158,
    'adjtimex': 159,
    'setrlimit': 160,
    'chroot': 161,
    'sync': 162,
    'acct': 163,
    'settimeofday': 164,
    'mount': 165,
    'umount2': 166,
    'swapon': 167,
    'swapoff': 168,
    'reboot': 169,
    'sethostname': 170,
    'setdomainname': 171,
    'iopl': 172,
    'ioperm': 173,
    'create_module': 174,
    'init_module': 175,
    'delete_module': 176,
    'get_kernel_syms': 177,
    'query_module': 178,
    'quotactl': 179,
    'nfsservctl': 180,
    'getpmsg': 181,
    'putpmsg': 182,
    'afs_syscall': 183,
    'tuxcall': 184,
    'security': 185,
    'gettid': 186,
    'readahead': 187,
    'setxattr': 188,
    'lsetxattr': 189,
    'fsetxattr': 190,
    'getxattr': 191,
    'lgetxattr': 192,
    'fgetxattr': 193,
    'listxattr': 194,
    'llistxattr': 195,
    'flistxattr': 196,
    'removexattr': 197,
    'lremovexattr': 198,
    'fremovexattr': 199,
    'tkill': 200,
    'time': 201,
    'futex': 202,
    'sched_setaffinity': 203,
    'sched_getaffinity': 204,
    'set_thread_area': 205,
    'io_setup': 206,
    'io_destroy': 207,
    'io_getevents': 208,
    'io_submit': 209,
    'io_cancel': 210,
    'get_thread_area': 211,
    'lookup_dcookie': 212,
    'epoll_create': 213,
    'epoll_ctl_old': 214,
    'epoll_wait_old': 215,
    'remap_file_pages': 216,
    'getdents64': 217,
    'set_tid_address': 218,
    'restart_syscall': 219,
    'semtimedop': 220,
    'fadvise64': 221,
    'timer_create': 222,
    'timer_settime': 223,
    'timer_gettime': 224,
    'timer_getoverrun': 225,
    'timer_delete': 226,
    'clock_settime': 227,
    'clock_gettime': 228,
    'clock_getres': 229,
    'clock_nanosleep': 230,
    'exit_group': 231,
    'epoll_wait': 232,
    'epoll_ctl': 233,
    'tgkill': 234,
    'utimes': 235,
    'vserver': 236,
    'mbind': 237,
    'set_mempolicy': 238,
    'get_mempolicy': 239,
    'mq_open': 240,
    'mq_unlink': 241,
    'mq_timedsend': 242,
    'mq_timedreceive': 243,
    'mq_notify': 244,
    'mq_getsetattr': 245,
    'kexec_load': 246,
    'waitid': 247,
    'add_key': 248,
    'request_key': 249,
    'keyctl': 250,
    'ioprio_set': 251,
    'ioprio_get': 252,
    'inotify_init': 253,
    'inotify_add_watch': 254,
    'inotify_rm_watch': 255,
    'migrate_pages': 256,
    'openat': 257,
    'mkdirat': 258,
    'mknodat': 259,
    'fchownat': 260,
    'futimesat': 261,
    'newfstatat': 262,
    'unlinkat': 263,
    'renameat': 264,
    'linkat': 265,
    'symlinkat': 266,
    'readlinkat': 267,
    'fchmodat': 268,
    'faccessat': 269,
    'pselect6': 270,
    'ppoll': 271,
    'unshare': 272,
    'set_robust_list': 273,
    'get_robust_list': 274,
    'splice': 275,
    'tee': 276,
    'sync_file_range': 277,
    'vmsplice': 278,
    'move_pages': 279,
    'utimensat': 280,
    'epoll_pwait': 281,
    'signalfd': 282,
    'timerfd_create': 283,
    'eventfd': 284,
    'fallocate': 285,
    'timerfd_settime': 286,
    'timerfd_gettime': 287,
    'accept4': 288,
    'signalfd4': 289,
    'eventfd2': 290,
    'epoll_create1': 291,
    'dup3': 292,
    'pipe2': 293,
    'inotify_init1': 294,
    'preadv': 295,
    'pwritev': 296,
    'rt_tgsigqueueinfo': 297,
    'perf_event_open': 298,
    'recvmmsg': 299,
    'fanotify_init': 300,
    'fanotify_mark': 301,
    'prlimit64': 302,
    'name_to_handle_at': 303,
    'open_by_handle_at': 304,
    'clock_adjtime': 305,
    'syncfs': 306,
    'sendmmsg': 307,
    'setns': 308,
    'getcpu': 309,
    'process_vm_readv': 310,
    'process_vm_writev': 311,
    'kcmp': 312,
    'finit_module': 313,
    'sched_setattr': 314,
    'sched_getattr': 315,
    'renameat2': 316,
    'seccomp': 317,
    'getrandom': 318,
    'memfd_create': 319,
    'kexec_file_load': 320,
    'bpf': 321,
    'execveat': 322,
    'userfaultfd': 323,
    'membarrier': 324,
    'mlock2': 325,
    'copy_file_range': 326,
    'preadv2': 327,
    'pwritev2': 328,
}

class SyscallFilter:
    """系统调用过滤器"""
    
    def __init__(self):
        self.libc = None
        self._load_libc()
        
        # 危险的系统调用列表
        self.dangerous_syscalls = {
            # 网络相关
            'socket', 'connect', 'bind', 'listen', 'accept', 'accept4',
            'sendto', 'recvfrom', 'sendmsg', 'recvmsg', 'shutdown',
            'socketpair', 'setsockopt', 'getsockopt', 'getsockname', 'getpeername',
            
            # 进程/线程控制
            'fork', 'vfork', 'clone', 'execve', 'execveat', 'kill', 'tkill', 'tgkill',
            'ptrace', 'wait4', 'waitid',
            
            # 文件系统修改
            'unlink', 'unlinkat', 'rmdir', 'rename', 'renameat', 'renameat2',
            'mkdir', 'mkdirat', 'mknod', 'mknodat', 'link', 'linkat', 
            'symlink', 'symlinkat', 'chmod', 'fchmod', 'fchmodat',
            'chown', 'fchown', 'fchownat', 'lchown', 'truncate', 'ftruncate',
            
            # 系统管理
            'mount', 'umount2', 'chroot', 'pivot_root', 'swapon', 'swapoff',
            'reboot', 'sync', 'fsync', 'fdatasync', 'syncfs',
            'sethostname', 'setdomainname', 'settimeofday', 'clock_settime',
            'adjtimex', 'clock_adjtime',
            
            # 权限/安全
            'setuid', 'setgid', 'setreuid', 'setregid', 'setresuid', 'setresgid',
            'setfsuid', 'setfsgid', 'setgroups', 'capget', 'capset',
            'personality', 'prctl', 'arch_prctl', 'modify_ldt',
            
            # 模块加载
            'init_module', 'finit_module', 'delete_module', 'create_module',
            
            # 内存管理（危险部分）
            'mlock', 'mlockall', 'munlock', 'munlockall', 'mprotect',
            
            # I/O控制
            'iopl', 'ioperm', 'ioctl',
            
            # 调试/跟踪
            'ptrace', 'process_vm_readv', 'process_vm_writev',
            
            # 时间管理
            'settimeofday', 'clock_settime', 'adjtimex',
            
            # 其他危险调用
            'acct', 'quotactl', 'syslog', 'vhangup', 'uselib',
            'lookup_dcookie', 'kexec_load', 'kexec_file_load',
            'add_key', 'request_key', 'keyctl', 'bpf', 'userfaultfd',
            'perf_event_open', 'fanotify_init', 'fanotify_mark'
        }
        
        # 允许的基本系统调用
        self.allowed_syscalls = {
            # 基本I/O
            'read', 'write', 'pread64', 'pwrite64', 'readv', 'writev',
            'preadv', 'pwritev', 'preadv2', 'pwritev2',
            
            # 文件操作（只读）
            'open', 'openat', 'close', 'stat', 'fstat', 'lstat', 'newfstatat',
            'access', 'faccessat', 'readlink', 'readlinkat',
            'getdents', 'getdents64', 'getcwd', 'lseek',
            
            # 内存管理（安全部分）
            'mmap', 'munmap', 'brk', 'mremap', 'madvise', 'mincore',
            
            # 信号处理
            'rt_sigaction', 'rt_sigprocmask', 'rt_sigreturn', 'rt_sigpending',
            'rt_sigtimedwait', 'rt_sigqueueinfo', 'rt_sigsuspend', 'sigaltstack',
            
            # 进程信息
            'getpid', 'getppid', 'gettid', 'getuid', 'getgid', 'geteuid', 'getegid',
            'getpgid', 'getpgrp', 'getsid', 'getgroups', 'getresuid', 'getresgid',
            
            # 时间相关
            'time', 'gettimeofday', 'clock_gettime', 'clock_getres', 'clock_nanosleep',
            'nanosleep', 'times', 'getitimer', 'alarm',
            
            # 资源限制
            'getrlimit', 'getrusage', 'sysinfo',
            
            # 调度
            'sched_yield', 'sched_getparam', 'sched_getscheduler',
            'sched_get_priority_max', 'sched_get_priority_min', 'sched_rr_get_interval',
            'sched_getaffinity', 'sched_getattr',
            
            # 事件/通知
            'poll', 'select', 'pselect6', 'ppoll', 'epoll_create', 'epoll_create1',
            'epoll_ctl', 'epoll_wait', 'epoll_pwait',
            
            # 其他安全调用
            'exit', 'exit_group', 'pause', 'restart_syscall', 'uname',
            'umask', 'dup', 'dup2', 'dup3', 'pipe', 'pipe2',
            'futex', 'set_tid_address', 'set_robust_list', 'get_robust_list',
            'getrandom', 'getcpu'
        }
    
    def _load_libc(self):
        """加载libc库"""
        try:
            libc_path = ctypes.util.find_library('c')
            if libc_path:
                self.libc = ctypes.CDLL(libc_path)
                logger.debug("已加载libc库")
            else:
                logger.warning("未找到libc库，系统调用过滤将被禁用")
        except Exception as e:
            logger.warning(f"加载libc库失败: {e}")
    
    def create_seccomp_filter(self) -> bool:
        """创建seccomp过滤器"""
        if not self.libc:
            logger.warning("libc未加载，无法创建seccomp过滤器")
            return False
        
        try:
            # 这是一个简化的seccomp实现
            # 在实际生产环境中，应该使用更复杂的BPF程序
            
            # 设置seccomp模式为过滤模式
            # 注意：这需要特殊的权限或capabilities
            result = self.libc.prctl(157, 2, 0, 0, 0)  # PR_SET_SECCOMP, SECCOMP_MODE_FILTER
            
            if result == 0:
                logger.debug("seccomp过滤器已激活")
                return True
            else:
                logger.warning(f"激活seccomp失败，返回码: {result}")
                return False
                
        except Exception as e:
            logger.warning(f"创建seccomp过滤器失败: {e}")
            return False
    
    def apply_restrictions(self) -> bool:
        """应用系统调用限制"""
        try:
            # 在当前进程中应用seccomp过滤器
            success = self.create_seccomp_filter()
            
            if success:
                logger.info("系统调用限制已应用")
            else:
                logger.warning("系统调用限制应用失败，将降级到其他安全措施")
            
            return success
            
        except Exception as e:
            logger.error(f"应用系统调用限制失败: {e}")
            return False

def create_restricted_environment():
    """创建受限的执行环境"""
    syscall_filter = SyscallFilter()
    return syscall_filter.apply_restrictions()

def get_dangerous_syscalls() -> set:
    """获取危险系统调用列表"""
    filter_instance = SyscallFilter()
    return filter_instance.dangerous_syscalls

def get_allowed_syscalls() -> set:
    """获取允许的系统调用列表"""
    filter_instance = SyscallFilter()
    return filter_instance.allowed_syscalls 